package cn.ad.server.web.servlet.v2.parser;

import cn.ad.server.web.spring.model.IAdserverRequest;
import cn.ad.server.web.spring.model.IAdserverResponse;
import cn.ad.server.web.spring.model.bes.BES;
import cn.ad.server.web.spring.model.bes.BES.BidRequest.Builder;
import cn.ad.server.web.spring.model.bes.BESBidRequest;
import cn.ad.server.web.spring.model.bes.BESBidResponse;
import com.google.protobuf.CodedOutputStream;
import com.googlecode.protobuf.format.JsonFormat;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * BES-Bid 请求解析类
 * @author wangwei
 */
public class BESBidServletParser extends HttpServletParserAdapter {

//	private static final String CONTENT_TYPE_PROTOBUF = "application/x-protobuf;charset=utf-8";
	private static final String CONTENT_TYPE_PROTOBUF = "application/octet-stream;charset=utf-8";
	
	/**
	 * 
	 */
	public BESBidServletParser() {
	}

	/* (non-Javadoc)
	 * @see cn.ad.server.web.servlet.parser.HttpServletParser#parse(javax.servlet.http.HttpServletRequest)
	 */
	@Override
	public IAdserverRequest parse(HttpServletRequest request) throws AdRequestParseException {
		BESBidRequest bidRequest = null;
		try {
			ServletInputStream inputStream = request.getInputStream();
			BESBidRequest besBidRequest = new BESBidRequest();
			Builder builder = besBidRequest.getBuilder();
			builder.mergeFrom(inputStream);
			besBidRequest.buildRequest();
			bidRequest = besBidRequest;
			//TODO TEST
			//System.out.println(printReqToJson(besBidRequest));
		} catch (Exception e) {
			throw new AdRequestParseException(e);
		}
		return bidRequest;
	}

	/* (non-Javadoc)
	 * @see cn.ad.server.web.servlet.parser.HttpServletParser#writeResponse(cn.falconnect.adserver.adapter.AdResponse, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	public void writeResponse(IAdserverResponse adResponse, HttpServletResponse response) throws AdRequestParseException {
		response.setContentType(CONTENT_TYPE_PROTOBUF);
		response.setHeader("Connection", "Keep-Alive");
		try {
			BESBidResponse besBidResponse = (BESBidResponse)adResponse;
			CodedOutputStream z = CodedOutputStream.newInstance(response.getOutputStream());
			besBidResponse.buildResponse().writeTo(z);
			z.flush();
		} catch (IOException e) {
			throw new AdRequestParseException(e);
		}
	}
	
	/**
	 * 打印tojson
	 * @param besBidRequest
	 * @return
	 * @throws IOException
	 */
	private String printReqToJson(BESBidRequest besBidRequest) throws IOException {
		JsonFormat format = new JsonFormat();
	       ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
	       BES.BidRequest bidRequest = besBidRequest.buildRequest();
	        format.print(bidRequest,byteArrayOutputStream);
	        String json = formatJson(byteArrayOutputStream.toString());
		return json;
	}
	
	/**
	 * 格式化为json
	 * @param json
	 * @return
	 */
	private String formatJson(String json){

        StringBuffer result = new StringBuffer();

        int length = json.length();
        int number = 0;
        char key = 0;

        //遍历输入字符串。
        for (int i = 0; i < length; i++)
        {
            //1、获取当前字符。
            key = json.charAt(i);

            //2、如果当前字符是前方括号、前花括号做如下处理：
            if((key == '[') || (key == '{') )
            {
                //（1）如果前面还有字符，并且字符为“：”，打印：换行和缩进字符字符串。
                if((i - 1 > 0) && (json.charAt(i - 1) == ':'))
                {
                    result.append('\n');
                    result.append(indent(number));
                }

                //（2）打印：当前字符。
                result.append(key);

                //（3）前方括号、前花括号，的后面必须换行。打印：换行。
                result.append('\n');

                //（4）每出现一次前方括号、前花括号；缩进次数增加一次。打印：新行缩进。
                number++;
                result.append(indent(number));

                //（5）进行下一次循环。
                continue;
            }

            //3、如果当前字符是后方括号、后花括号做如下处理：
            if((key == ']') || (key == '}') )
            {
                //（1）后方括号、后花括号，的前面必须换行。打印：换行。
                result.append('\n');

                //（2）每出现一次后方括号、后花括号；缩进次数减少一次。打印：缩进。
                number--;
                result.append(indent(number));

                //（3）打印：当前字符。
                result.append(key);

                //（4）如果当前字符后面还有字符，并且字符不为“，”，打印：换行。
                if(((i + 1) < length) && (json.charAt(i + 1) != ','))
                {
                    result.append('\n');
                }

                //（5）继续下一次循环。
                continue;
            }

            //4、如果当前字符是逗号。逗号后面换行，并缩进，不改变缩进次数。
            if((key == ','))
            {
                result.append(key);
                result.append('\n');
                result.append(indent(number));
                continue;
            }

            //5、打印：当前字符。
            result.append(key);
        }
        return result.toString();
    }
	/**
	 * indent
	 * @param number
	 * @return
	 */
    private String indent(int number){
        StringBuffer result = new StringBuffer();
        for(int i = 0; i < number; i++)
        {
            result.append(SPACE);
        }
        return result.toString();
    }
    
    private static String SPACE = "   ";


}
